package com.lmt.ymcc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.lmt.ymcc.constant.SmsConstant;
import com.lmt.ymcc.domain.Login;
import com.lmt.ymcc.domain.User;
import com.lmt.ymcc.domain.UserAccount;
import com.lmt.ymcc.domain.UserBaseInfo;
import com.lmt.ymcc.dto.RegisterDto;
import com.lmt.ymcc.feign.UaaFeign;
import com.lmt.ymcc.mapper.UserAccountMapper;
import com.lmt.ymcc.mapper.UserBaseInfoMapper;
import com.lmt.ymcc.mapper.UserMapper;
import com.lmt.ymcc.result.JSONResult;
import com.lmt.ymcc.service.IUserService;
import com.lmt.ymcc.utils.AssertUtil;
import com.lmt.ymcc.utils.BitStatesUtils;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author AmazingXu
 * @since 2022-08-05
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {


    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UaaFeign uaaFeign;

    @Autowired
    private UserBaseInfoMapper userBaseInfoMapper;

    @Autowired
    private UserAccountMapper userAccountMapper;

    private final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    /**
    * @Title: register
    * @Description: 用户注册方法
    * @Author: Amazing
    * @Version: 1.0
    * @Date:  2022/8/7 16:54
    * @Parameters: [registerDto]
    * @Return com.lmt.ymcc.result.JSONResult
    */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void register(RegisterDto registerDto) {
        // 判断用户是否已经注册过了
        AssertUtil.isFalse(existUserByPhone(registerDto.getMobile()), "此账号已注册");
        // 判断手机验证码是否存在
        String SmsCodeKey =  SmsConstant.SMS_CODE_KEY + registerDto.getMobile();
        String smsCodeValue = (String) redisTemplate.opsForValue().get(SmsCodeKey);
        AssertUtil.isNotNull(smsCodeValue,"验证码不存在");
        // 判断验证码是否正确
        AssertUtil.isTrue(checkSmsCode(smsCodeValue, registerDto), "验证码错误");
        // 如果正确就进行用户信息存储，login
         Long loginId = insertLoginAndGetLoginId(registerDto);
        // 存储user表信息
        insertRelateUserTables(registerDto, loginId);
        // 删除redis中的验证码信息
        String imgCodeKey = (String)redisTemplate.opsForValue().get(SmsConstant.IMG_CODE_KEY);
        removeSMSCodeRedisKey(SmsCodeKey,imgCodeKey);
    }


    // 删除redis中的验证码信息
    private void removeSMSCodeRedisKey(String smsCodeKey, String imgCodeKey) {
        redisTemplate.delete(smsCodeKey);
        redisTemplate.delete(imgCodeKey);
    }

    // 存储user服务相关表信息
    private void insertRelateUserTables(RegisterDto registerDto, Long loginId) {
        User user = insertUserAndGetUser(registerDto,loginId);
        insertUserBaseInfo(user,registerDto);
        insertUserAccount(user);
    }

    // 存储userAccount表信息
    private void insertUserAccount(User user) {
        UserAccount userAccount = new UserAccount();
        userAccount.setId(user.getId());
        userAccount.setCreateTime(user.getCreateTime());
        userAccountMapper.insert(userAccount);
    }

    // 存储userbaseinfo表信息
    private void insertUserBaseInfo(User user, RegisterDto registerDto) {
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setId(user.getId());
        userBaseInfo.setCreateTime(user.getCreateTime());
        userBaseInfo.setRegChannel(registerDto.getRegChannel());
        userBaseInfoMapper.insert(userBaseInfo);
    }

    // 存储user表信息
    private User insertUserAndGetUser(RegisterDto registerDto, Long loginId) {
        User user = new User();
        user.setPhone(registerDto.getMobile());
        user.setNickName(registerDto.getMobile());
        user.setCreateTime(new Date().getTime());
        Long states = BitStatesUtils.batchAddState(0L,
                BitStatesUtils.OP_REGISTED,
                BitStatesUtils.OP_ACTIVED,
                BitStatesUtils.OP_AUTHED_PHONE);
        user.setLoginId(loginId);
        user.setBitState(states);
        userMapper.insert(user);
        return user;
    }

    // 判断验证码是否正确
    private Boolean checkSmsCode(String smsCodeValue, RegisterDto registerDto) {
        return StringUtils.equals(registerDto.getSmsCode(), smsCodeValue);
    }

    // 存储login信息并获取主键
    private Long insertLoginAndGetLoginId(RegisterDto registerDto) {
        // 设置login信息
        Login login = new Login();
        login.setUsername(registerDto.getMobile());
        login.setPassword(encoder.encode(registerDto.getPassword()));
        login.setType(registerDto.getRegChannel());
        // 此处一定要加序列化
        JSONResult<Login> jsonResult = uaaFeign.saveOrUpdate(login);
        Login LoginResult = jsonResult.getData();
        return LoginResult.getId();
    }

    // 判断账号是否注册过
    boolean existUserByPhone(String phone){
        EntityWrapper<User> wrapper = new EntityWrapper<>();
        wrapper.eq("phone", phone);
        List<User> users = userMapper.selectList(wrapper);
        return users != null && users.size() > 0;
    }

}
